﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Weazel.Willows.Model
{
	public partial class QueueConnectorReaderInterface
		: QueueReaderInterface, IQueueConnectorReader
	{
		private Weazel.Willows.RefinedModel.InPort dataInPort;
		public Weazel.Willows.RefinedModel.InPort DataInPort
		{
			get { return dataInPort; }
		}

		private Weazel.Willows.RefinedModel.InPort canReadPort;
		public Weazel.Willows.RefinedModel.InPort CanReadPort
		{
			get { return canReadPort; }
		}

		private Weazel.Willows.RefinedModel.OutPort doReadPort;
		public Weazel.Willows.RefinedModel.OutPort DoReadPort
		{
			get { return doReadPort; }			
		}

		public string CanReadSignalName
		{
			get { return QueuePrefix + LocalName + "_can_read"; }
		}

		public string DequeueSignalName
		{
			get { return QueuePrefix + LocalName + "_port"; }
		}

		public string DoReadSignalName
		{
			get { return QueuePrefix + LocalName + "_do_read"; }
		}
	
		#region Signal/Port Insertions
		private void insertDataInPort(RefinedModel.Datapath datapath)
		{
			dataInPort =
				new Weazel.Willows.RefinedModel.InPort(TypeRegistry, datapath, DequeueSignalName, Type);

			datapath.InPorts.Add(dataInPort.LocalName, dataInPort);
		}

		private void insertCanReadPort(RefinedModel.Datapath datapath)
		{
			canReadPort =
				new Weazel.Willows.RefinedModel.InPort(TypeRegistry, datapath, CanReadSignalName, (Type)TypeRegistry["boolean"]);

			datapath.InPorts.Add(canReadPort.LocalName, canReadPort);
		}

		private void insertDoReadPort(RefinedModel.Datapath datapath)
		{
			doReadPort =
				new Weazel.Willows.RefinedModel.OutPort(TypeRegistry, datapath, DoReadSignalName, (Type)TypeRegistry["boolean"]);

			datapath.OutPorts.Add(doReadPort.LocalName, doReadPort);
		}
		#endregion

		public override void Refine(RefinedModel.Model model)
		{
			if (!(Parent is Module))
			{
				// Refinement of queue connectors presently only has meaning for 
				// connectors attached to Modules
				throw new NotSupportedException();
			}

			// parent must be module, cast 
			Module module = Parent as Module;

			// refine the model (if needed)
			module.Refine(model);

			// get a referente to the datapath
			RefinedModel.Datapath datapath = module.Datapath;

			insertCanReadPort(datapath);
			insertDataInPort(datapath);
			insertDoReadPort(datapath);

			// refine child readers..
			foreach (IQueueReaderInterface reader in readers)
				reader.Refine(model);
		}
	}
}
